#include "atom.h"
#include "main.h"

real f02 = real(3./16.);
real f12 = real(251./360.);
real f32 = real(11./18.);
real f42 = real(1./6.);
real f52 = real(1./60.);


atom::atom(int t0, int id0, real m0, vec3 l0, real k0):f(),r0(l0),r1(),r2(),r3(),r4(),r5()
{
    mass = m0;
    type = t0;
    ir0  = l0;
    id   = id0;
    k    = k0;	
    binning();

}

vec3* atom::getR0()
{
    return &r0;
}

void atom::predict(){

    r0 += r1+r2+r3+r4+r5;
    r1 += 2.*r2+3.*r3+4.*r4+5.*r5;
    r2 += 3.*r3+6.*r4+10.*r5;
    r3 += 4.*r4+10.*r5;
    r4 += 5.*r5;
}

void atom::correct(){

    vec3 rerr=r2-recip_em*f;

    r0 -= f02 * rerr;
    r1 -= f12 * rerr;
    r2 -= rerr;
    r3 -= f32 * rerr;
    r4 -= f42 * rerr;
    r5 -= f52 * rerr;
}

void atom::binning(){

    kx = int(r0.x * DXI) + 1;
    ky = int(r0.y * DYI) + 1;
    kz = int(r0.z * DZI) + 1;

}

void atom::periodicx(){
	
	 r0.x -= XSIZE * int(r0.x * XI2 - 1.);
}

void atom::periodicy(){

	 r0.y -= YSIZE * int(r0.y * YI2 - 1.);
}

void atom::periodicz(){

	 r0.z -= ZSIZE * int(r0.z * ZI2 - 1.);
}

void atom::addforce(vec3 force){
        
	f += force;
}

void atom::clearforce(){

	f = VO;
}


void atom::tether(){
	
	f += k * (ir0 - r0);
}


void atom::info(){
    
    cout.precision(2);
    cout.setf(ios::fixed); 
    
    cout<<"-------------------Atom Info-----------------------"<<endl;
    cout<<"|\tType  |  "<<type<<endl;
    cout<<"|\tID    |  "<<id<<endl;
    cout<<"|\tMass  |  "<<mass<<endl;
    cout<<"|\tR0    |  ("<<r0.x<<", "<<r0.y<<", "<<r0.z<<")"<<endl;
    cout<<"|\tR1    |  ("<<r1.x<<", "<<r1.y<<", "<<r1.z<<")"<<endl;
    cout<<"|\tK     |  (" <<kx<<",   "<<ky<<",   "<<kz<< ")"<<endl;
    cout<<"---------------------------------------------------"<<endl;

}
